package com.ylz.sjzx.sio.common.core.core.Interceptor;

import com.ylz.sjzx.sio.common.core.core.container.ChainScanner;
import com.ylz.sjzx.sio.common.core.core.container.common.ContainerSortComparator;
import com.ylz.sjzx.sio.common.core.exception.InterceptorAfterException;
import com.ylz.sjzx.sio.common.core.exception.InterceptorInterruptException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created with IntelliJ IDEA.
 * <p> Description:
 * 拦截器容器
 * <p>
 */
public class InterceptorChain {

    /**
     * 日志记录器
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(InterceptorChain.class);

    /**
     * 处理请求拦截器
     */
    private List<IInterceptor> interceptors = new ArrayList<>();

    /**
     * 客户端初始化异常处理拦截器,仅调用Reserved类型的处理器进行处后置理
     */
    private List<IInterceptor> invokerInitFailPostInterceptor = new ArrayList<>();

    /**
     * 继承reserved类型拦截器的子类列表
     */
    private List<IInterceptor> extendReservedInterceptors = new ArrayList<>();

    /**
     * 用来保存Interceptor与API接口名的缓存
     */
    private Map<String, Map<String, String>> interceptorCache = new ConcurrentHashMap<>();

    public InterceptorChain() {
        List<IInterceptor> customInterceptors = ChainScanner.scanInterceptor();
        this.interceptors.addAll(customInterceptors);

        this.invokerInitFailPostInterceptor.addAll(this.extendReservedInterceptors);

        ContainerSortComparator<IInterceptor> comparator =
                new ContainerSortComparator<>(InterceptorType.RESERVED.getList());
        Collections.sort(this.interceptors, comparator);

        //按照注解标志的顺序排序
        comparator.setDesc(true);
        Collections.sort(this.invokerInitFailPostInterceptor, comparator);
    }

    /**
     * 预处理，正序执行拦截器
     */
    public void preHandle() {

        for (IInterceptor interceptor : this.interceptors) {
            boolean result = interceptor.preHandle();
            if (!result) {
                throw new InterceptorInterruptException(interceptor.getClass().getName() + "前置处理拒绝了该请求");
            }
        }
    }

    /**
     * 后置处理，逆序执行拦截器
     */
    public void postHandle() {

        int size = this.interceptors.size();
        for (int x = size - 1; x >= 0; x--) {
            IInterceptor interceptor = this.interceptors.get(x);
            boolean result = interceptor.postHandle();
            if (!result) {
                throw new InterceptorAfterException(interceptor.getClass().getName() + "后置处理拒绝了该请求");
            }

        }
    }

    /**
     * finally处理
     * InvokerInitFailException因为事件发生在RequestContext.initContext阶段,
     * 所以这个异常没有任何输入上下文环境,故需要进行特殊处理。
     */
    public void afterCompletion() {
        for (IInterceptor interceptor : this.invokerInitFailPostInterceptor) {
            //捕获所有afterCompletion抛出的MAPIException异常,仅仅记录日志
            try {
                interceptor.afterCompletion();
            } catch (Exception e) {
                LOGGER.error("拦截器afterCompletion事件抛出异常:" + e.getMessage(), e);
            }
        }
        return;
    }
}
